/*
 * Copyright (C) 2010 Seapeak.Xu
 *
 * fostmq may be copied only under the terms of the GNU General
 * Public License V3, which may be found in the fostmq source kit.
 *
 * Created on: 2010-7-27
 * Author: Seapeak.Xu
 */

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "fostmq_conf.h"
#include "fost_logger.h"
#include "fost_mem.h"
#include "fost_event.h"
#include "fost_propreader.h"
#include "fost_sock.h"
#include "fostmq_service.h"
#include "fost_taskpool.h"
#include "fost_mgnb.h"
#include "fost_proc.h"
#include "fost_notifypool.h"
#include "fost_notifythread.h"
#include "fost_notify.h"

static void kill_signal(int signal);
static void empty_signal(int signal);

int main(int argc, char **argv)
{
	int result = 0;
	
	if (2 != argc)
	{
		log_error(
				"Starting is error.Error info is: No args that is the conf file path");
		return EINVAL;
	}

	if (0 != (result = prop_init(argv[1], set_conf)))
	{
		log_error("init error.read conf file is error.Errno:%d,Info:%s.",
				result,strerror(result));
		return result;
	}

	if (0 != (result = logger_init(g_logpath, g_logprefix, g_loglines, g_loglevel)))
	{
		log_error("init error.read conf file is error.Errno:%d,Info:%s.",
				result, strerror(result));
		return 0;
	}
	do
	{
		if(0 == g_daemon)
		{
			daemon_init(false);
		}
		else
		{
			daemon_init(true);
		}

		umask(0);

		if (0 != service_init(g_storepath, g_nonleafnodes, g_chucksize * 1024 * 1024,g_synctime))
		{
			log_error("init the service is error.");
			break;
		}

		char cwd[PATH_LEN];
		memset(cwd,0,PATH_LEN);
		getcwd(cwd,PATH_LEN);
		log_debug("File:%s,Line:%d,Function:%s.current path is %s.",__FILE__,__LINE__,__FUNCTION__,cwd);
		log_debug("File:%s,Line:%d,Function:%s.init the service is over.",__FILE__,__LINE__,__FUNCTION__);

		do
		{
			int sock;
			if (-1 == (sock = server_sock_init(&g_bindip, g_port, g_connections,
					g_timeout)))
			{
				log_error("socket init is error.");
				break;
			}

			log_debug("File:%s,Line:%d,Function:%s.init the socket is over.",__FILE__,__LINE__,__FUNCTION__);

			do
			{
				if( 0 != taskpool_init(g_threadpools,g_timeout,deal_request_header, deal_request_body))
				{
					log_error("task pool init is error.");
					break;
				}

				log_debug("File:%s,Line:%d,Function:%s.init the task pool is over.",__FILE__,__LINE__,__FUNCTION__);

				do
				{
					if (0 != notifypool_init(g_threadpools,notify_read_event))
					{
						log_error("notify pool init is error.");
						break;
					}

					if(0 != workthread_init(g_threadpools,g_stacksize))
					{
						log_error("create work thread is pool.");
						break;
					}
					log_debug("File:%s,Line:%d,Function:%s.init the thread pool is over.",__FILE__,__LINE__,__FUNCTION__);

					struct sigaction act;
					memset(&act, 0, sizeof(act));
					sigemptyset(&act.sa_mask);

					act.sa_handler = empty_signal;
					if(sigaction(SIGUSR1, &act, NULL) < 0 || sigaction(SIGUSR2, &act, NULL) < 0)
					{
						log_error("File:%s,Line:%d,Function:%s.regedit the hander for signal is error.Errno:%d,Info:%s.",
										__FILE__,__LINE__,__FUNCTION__, errno, strerror(errno));
						break;
					}

					act.sa_handler = empty_signal;
					if(sigaction(SIGHUP, &act, NULL) < 0)
					{
						log_error("File:%s,Line:%d,Function:%s.regedit the hander for signal is error.Errno:%d,Info:%s.",
							__FILE__,__LINE__,__FUNCTION__, errno, strerror(errno));

						break;
					}

					act.sa_handler = SIG_IGN;
					if(sigaction(SIGPIPE, &act, NULL) < 0)
					{
						log_error("File:%s,Line:%d,Function:%s.regedit the hander for signal is error.Errno:%d,Info:%s.",
										__FILE__,__LINE__,__FUNCTION__, errno, strerror(errno));
						break;
					}

					act.sa_handler = kill_signal;
					if(sigaction(SIGINT, &act, NULL) < 0 || sigaction(SIGTERM, &act, NULL) < 0
							|| sigaction(SIGABRT, &act, NULL) < 0 || sigaction(SIGQUIT, &act, NULL) < 0)
					{
						log_error("File:%s,Line:%d,Function:%s.regedit the hander for signal is error.Errno:%d,Info:%s.",
																__FILE__,__LINE__,__FUNCTION__, errno, strerror(errno));
						break;
					}

					log_debug("File:%s,Line:%d,Function:%s.init the fostmq is over,begin accept the client.",__FILE__,__LINE__,__FUNCTION__);

					sock_accept(sock, g_threadpools);
					notifypool_destroy();

				}while(false);
				taskpool_destroy();

			}while(false);
			close(sock);

		}while(false);
		service_destroy();

	}while(false);
	logger_close();

	return 0;
}

static void kill_signal(int signal)
{
	log_emery("Accept the signal:%d,now stop the service.",signal);
	g_loop = false;
	sync_queue();
	//threadpool_destroy();
	sync_queue();
}
static void empty_signal(int signal)
{

}
